import nacl from "tweetnacl";
import Base58 from './base58';
import CryptoJS from 'crypto-js';

export function hex2Bytes(str: string) {
    var pos = 0;
    var len = str.length;
    if (len % 2 != 0) {
        return null;
    }
    len /= 2;
    var hexA = new Array();
    for (var i = 0; i < len; i++) {
        var s = str.substr(pos, 2);
        var v = parseInt(s, 16);
        if (v >= 127) v = v - 255 - 1
        hexA.push(v);
        pos += 2;
    }

    var uintarr = new Uint8Array(hexA.length);
    for (var i = 0; i < hexA.length; i++) {
        uintarr[i] = hexA[i];
    }
    return uintarr;
}

export function hex2Bytes_any(str: string) {
    var pos = 0;
    var len = str.length;
    len /= 2;
    var hexA = new Array();
    for (var i = 0; i < len; i++) {
        var s = str.substr(pos, 2);
        var v = parseInt(s, 16);
        if (v >= 127) v = v - 255 - 1
        hexA.push(v);
        pos += 2;
    }

    var uintarr = new Uint8Array(hexA.length);
    for (var i = 0; i < hexA.length; i++) {
        uintarr[i] = hexA[i];
    }
    return uintarr;
}

function randomString(len: number) {
    len = len || 32;
    var $chars = 'ABCDEFGHJKMNPQRSTWXYZabcdefhijkmnprstwxyz2345678';
    /****默认去掉了容易混淆的字符oOLl,9gq,Vv,Uu,I1****/
    var maxPos = $chars.length;
    var pwd = '';
    for (let i = 0; i < len; i++) {
        pwd += $chars.charAt(Math.floor(Math.random() * maxPos));
    }
    return pwd;
}

export function hex2Bytes_Random(len: number) {
    var pos = 0;
    var hexA = new Array();
    let str = randomString(len);
    for (var i = 0; i < len; i++) {
        var s = str.substr(pos, 2);
        var v = parseInt(s, 16);
        if (v >= 127) v = v - 255 - 1
        hexA.push(v);
        pos += 2;
    }

    var uintarr = new Uint8Array(hexA.length);
    for (var i = 0; i < hexA.length; i++) {
        uintarr[i] = hexA[i];
    }
    return uintarr;
}


export function bytes2Hex(arr: Uint8Array) {
    var uintarr = new Uint8Array(arr.length);
    for (var i = 0; i < arr.length; i++) {
        uintarr[i] = arr[i];
    }

    var str = "";
    for (var i = 0; i < uintarr.length; i++) {
        var tmp = uintarr[i].toString(16);
        if (tmp.length == 1) {
            tmp = "0" + tmp;
        }
        str += tmp;
    }
    return str;
}

export function randomSeed() {
    var numArr = new Uint8Array(32);
    for (var i = 0; i < numArr.length; i++) {
        numArr[i] = Math.random() * 255;
    }
    var temp = bytes2Hex(numArr) + "#" + new Date().getTime()+"smartxApp-2021-09-24";

    console.log(temp)

    temp = CryptoJS.SHA256(temp).toString();

    console.log()

    return temp;
};

export const checkAddress = (address: string) => {
    var decode58 = Base58.decodeArray(address);

    var temp = new Uint8Array(21);
    for (var i = 0; i < temp.length; i++) {
        temp[i] = decode58[i];
    }
    var data = bytes2Hex(temp);
    var hash1 = CryptoJS.SHA256(data).toString();
    var hash2 = CryptoJS.SHA256(hash1).toString();
    hash2 = hex2Bytes(hash2);
    var buffer = new Uint8Array(25);
    for (var i = 0; i < temp.length; i++) {
        buffer[i] = temp[i];
    }
    for (var i = 0; i < 4; i++) {
        buffer[21 + i] = hash2[i];
    }
    var b58 = Base58.encode(buffer);

    return address == b58;
}


export function sign(keyPair: any, data: string) {
    function _sign(privateKey: any, msg: any) {
        /*----------- convert the privateKey(base58 32) to secretKey(Uint8Array 64) ----------*/
        var secretKeyFull = privateKey;
        /*----------- convert the msg(string) to msg(Uint8Array ) ---------*/
        var msgByte = msg;
        var msgUnit8Array = new Uint8Array(msgByte.length);
        msgUnit8Array.set(msgByte);
        var signedMsg = nacl.sign.detached(msgUnit8Array, secretKeyFull);
        return signedMsg;
    }

    var dataBytes = hex2Bytes(data)
    var sign = _sign(keyPair.secretKey, dataBytes);
    var buffer = new Uint8Array(sign.length + keyPair.publicKey.length);
    for (var i = 0; i < sign.length; i++) {
        buffer[i] = sign[i];
    }
    for (var i = 0; i < keyPair.publicKey.length; i++) {
        buffer[i + sign.length] = keyPair.publicKey[i];
    }

    return bytes2Hex(buffer);
};

export function keyPairFromSeed(seedStr: string) {
    var seed = hex2Bytes(seedStr);
    if (!seed) {
        return null;
    }
    var numArr = new Uint8Array(32);
    for (var i = 0; i < seed.length; i++) {
        numArr[i] = seed[i];
    }
    var keyPair = nacl.sign.keyPair.fromSeed(numArr);
    // KeyPair.randomSeed = seed;
    return keyPair;
};

export function toAddress(publicKey: Uint8Array) {
    var publicKeyHex = bytes2Hex(publicKey);
    // ToAddress
    var sha256 = CryptoJS.SHA256(publicKeyHex).toString();
    var rmd160 = CryptoJS.RIPEMD160(sha256).toString();
    rmd160 = hex2Bytes(rmd160);

    var temp = new Uint8Array(21);
    temp[0] = 1;
    for (var i = 0; i < 20; i++) {
        temp[i + 1] = rmd160[i];
    }

    var data = bytes2Hex(temp);
    // Base58CheckEncode
    var hash1 = CryptoJS.SHA256(data).toString();
    var hash2 = CryptoJS.SHA256(hash1).toString();
    hash2 = hex2Bytes(hash2);

    var buffer = new Uint8Array(25);
    for (var i = 0; i < temp.length; i++) {
        buffer[i] = temp[i];
    }
    for (var i = 0; i < 4; i++) {
        buffer[21 + i] = hash2[i];
    }
    var b58 = Base58.encode(buffer);

    return b58;
};
